home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / programming / c / awin / awindemo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-05-17  |  13.3 KB  |  484 lines

  1. /* awindemo.c
  2.  
  3.   Simple example on how to use awin.
  4.  
  5.   Has three effects, dummy 16bit `pseudo'plasma,
  6.   8bit rotatezoomer and tunnel.
  7.  
  8.   compiled with ppc-amigaos-gcc 2.7.2.1:
  9.  
  10.   rotzoom runs ~198fps in 64x48 dbuffer off pal screen on 603p@240/060,
  11.   ~138fps 128x96, ~65fps 256x180 and ~45fps 320x240
  12.  
  13.   tunnel runs ~109fps (slow because of 128k table lookup),
  14.   ~88fps 128x96, ~51fps 256x180 and ~38fps 320x240
  15.  
  16.   all effects are calculating 320x240 chunky framebuffer.
  17.  
  18. */
  19.  
  20. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <strings.h>
  23. #include <math.h>
  24. #ifndef M_PI
  25. #  define M_PI 3.14159265358979323846
  26. #endif
  27.  
  28. #include "awin.h"
  29.  
  30. #define AWINDEMOVERSION "awindemo 1.0.13"
  31.  
  32. #define PLASMA_TIME 5000
  33. #define PLASMA_WIDTH 320
  34. #define PLASMA_HEIGHT 240
  35. #define PLASMA_DEPTH 16
  36.  
  37. #define ROTZOOM_TIME 20000
  38. #define ROTZOOM_WIDTH 320
  39. #define ROTZOOM_HEIGHT 240
  40. #define ROTZOOM_DEPTH 8
  41.  
  42. #define TUNNEL_TIME 20000
  43. #define TUNNEL_WIDTH 320
  44. #define TUNNEL_HEIGHT 240
  45. #define TUNNEL_DEPTH 8
  46.  
  47. #define DEF_WIDTH 320
  48. #define DEF_HEIGHT 240
  49.  
  50. #define SINTAB90 1024
  51. #define SINTAB360 (SINTAB90*4)
  52.  
  53.  
  54. unsigned long __stack=20480;
  55.  
  56. #if defined(AW_PPC)
  57. void __chkabort(void);
  58. void __chkabort(void){}
  59. #else 
  60. void __regargs __chkabort(void);
  61. void __regargs __chkabort(void){}
  62. #endif
  63.  
  64.  
  65.  
  66. /* this plasma isn't really plasma but simple routine to
  67.    generate 16bit test chunky */
  68.  
  69. #define limr(x) (((x)<0)?0:(((x)>31)?31:(x)))
  70. #define limg(x) (((x)<0)?0:(((x)>63)?63:(x)))
  71. #define limb(x) (((x)<0)?0:(((x)>31)?31:(x)))
  72. #define truncr(x) ((x)&31)
  73. #define truncg(x) ((x)&63)
  74. #define truncb(x) ((x)&31)
  75. #define torgb565(r,g,b) ((r)<<11|(g)<<5|(b))
  76.  
  77. void plasma(struct awchunky *chunky,ULONG time) {
  78.  
  79.   ULONG x,y,
  80.     *p=(ULONG *)chunky->framebuffer;
  81.   ULONG r,g,b;
  82.  
  83.   r=time/64+1;
  84.   g=time/32+3;
  85.   b=-(time/16+5);
  86.  
  87.   for (y=0; y<chunky->height; y++) {
  88.  
  89.     r+=(((y+time/100)/13)&7)-3;
  90.     g+=7-((y/11)&15);
  91.     b+=((y/7)&31)-15;
  92.  
  93.     for (x=0; x<chunky->width_align; x+=8)
  94.  
  95.       *p++=
  96.         torgb565(truncr(r),truncg(g),truncb(b))<<16|
  97.         torgb565(truncr(r+1),truncg(g+1),truncb(b+1)),
  98.  
  99.       *p++=
  100.         torgb565(truncr(r+2),truncg(g+2),truncb(b+2))<<16|
  101.         torgb565(truncr(r+3),truncg(g+3),truncb(b+3)),
  102.  
  103.       *p++=
  104.         torgb565(truncr(r+4),truncg(g+4),truncb(b+4))<<16|
  105.         torgb565(truncr(r+5),truncg(g+5),truncb(b+5)),
  106.  
  107.       *p++=
  108.         torgb565(truncr(r+6),truncg(g+6),truncb(b+6))<<16|
  109.         torgb565(truncr(r+7),truncg(g+7),truncb(b+7)),
  110.  
  111.         r+=8,g+=8,b+=8;
  112.   }
  113. }
  114.  
  115.  
  116. LONG *init_sintab(void) {
  117.   LONG *sintab,i;
  118.  
  119.   sintab=malloc(sizeof(LONG)*(SINTAB360+SINTAB90));
  120.   if (!sintab) {
  121.     printf("no memory for sintab\n");
  122.     return NULL;
  123.   }
  124.   for(i=0; i<(SINTAB360+SINTAB90); i++) {
  125.     sintab[i]=sin(M_PI/180.0*i*360.0/SINTAB360)*32768;
  126.   }
  127.   return sintab;
  128. }
  129.  
  130. /* this routine "taken" from QMap :) */
  131.  
  132. void rotzoom(struct awchunky *chunky,ULONG time,
  133.   ULONG *alpha,LONG *sintab,UBYTE *pic) {
  134.  
  135.   ULONG x,y,tx,ty,tx2,ty2,
  136.     *p=(ULONG *)chunky->framebuffer;
  137.   LONG aktsin,aktcos;
  138.  
  139.   aktsin=2*sintab[*alpha&(SINTAB360-1)];
  140.   aktcos=2*sintab[(*alpha&(SINTAB360-1))+SINTAB90];
  141.  
  142.   /* spend 10 seconds on SINTAB360 degrees */
  143.   *alpha=time/(10000.0/SINTAB360);
  144.  
  145.   tx2=-100*sintab[(5*(*alpha)+23)&(SINTAB360-1)];
  146.   ty2=-100*sintab[((7*(*alpha)+71)&(SINTAB360-1))+SINTAB90];
  147.   for (y=0; y<chunky->height; y++) {
  148.     tx=tx2;
  149.     ty=ty2;
  150.     for (x=0; x<chunky->width_align; x+=16)
  151.  
  152.       *p++=pic[((ty>>9)&(0x7f<<7))+((tx>>16)&0x7f)]<<24|
  153.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<16|
  154.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<8|
  155.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)],
  156.  
  157.       *p++=pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<24|
  158.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<16|
  159.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<8|
  160.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)],
  161.  
  162.       *p++=pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<24|
  163.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<16|
  164.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<8|
  165.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)],
  166.  
  167.       *p++=pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<24|
  168.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<16|
  169.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)]<<8|
  170.            pic[(((ty+=aktcos)>>9)&(0x7f<<7))+(((tx+=aktsin)>>16)&0x7f)],
  171.  
  172.       ty+=aktcos, tx+=aktsin; /* !! */
  173.  
  174.     tx2+=aktcos;
  175.     ty2-=aktsin;
  176.     aktsin-=1<<8;
  177.     aktcos+=1<<8;
  178.   }
  179. }
  180.  
  181.  
  182. UWORD *init_tunnel(void) {
  183.   UWORD *tunneltab;
  184.   LONG x,y;
  185.   ULONG xx,yy;
  186.   UWORD *tab;
  187.  
  188.   tunneltab=malloc(TUNNEL_WIDTH*TUNNEL_HEIGHT*sizeof(UWORD));
  189.   if (!tunneltab) {
  190.     printf("no memory for tunneltab\n");
  191.     return NULL;
  192.   }
  193.  
  194.   /* again this stuff shamelesly ripped. */
  195.  
  196.   tab=tunneltab;
  197.  
  198.   for (y=TUNNEL_HEIGHT/2; y>-TUNNEL_HEIGHT/2; y--) {
  199.     for (x=-TUNNEL_WIDTH/2; x<TUNNEL_WIDTH/2; x++) {
  200.       if (x | y) {
  201.         yy = (int) (6000 / sqrt((double)(x*x+y*y))) & 0xff;
  202.         xx = (int) (atan2((double)y, (double)x) * (256/M_PI)) &0xff;
  203.         *tab++ = yy<<8 | xx;
  204.       } else {
  205.         *tab++ = 0;
  206.       }
  207.     }
  208.   }
  209.   return tunneltab;
  210. }
  211.  
  212. UBYTE *init_texture(struct awfile *pic) {
  213.   UBYTE *texture=NULL;
  214.  
  215.   if (pic) {
  216.  
  217.     if (pic->size!=256*256) {
  218.       printf("tunnel texture size not 256*256\n");
  219.       awfreefile(pic);
  220.       return NULL;
  221.     }
  222.  
  223.     texture=malloc(256*256*2);
  224.     if (!texture) {
  225.       printf("no memory for texture\n");
  226.       return NULL;
  227.     }
  228.  
  229.     /* copy texture to mem twice */
  230.     memcpy(texture+0*256*256,pic->data,256*256);
  231.     memcpy(texture+1*256*256,pic->data,256*256);
  232.     awfreefile(pic);
  233.   }
  234.   return texture;
  235. }
  236.  
  237. void tunnel(struct awchunky *chunky,ULONG time,
  238.   UWORD *position,UWORD *tunneltab,LONG *sintab,UBYTE *texture) {
  239.  
  240.   ULONG cnt=(chunky->width_align>>4)*chunky->height,
  241.     index=0;
  242.   ULONG *p=(ULONG *)chunky->framebuffer;
  243.   UBYTE *t=&texture[*position];
  244.  
  245.   /* move along in texture */
  246.   *position=
  247.     ((time/4-sintab[(time/3+SINTAB90)&(SINTAB360-1)]/256)&0xff)<<8|
  248.     ((time/32+sintab[(time/2)&(SINTAB360-1)]/128)&0xff);
  249.  
  250.   while (cnt--)
  251.     *p++=t[tunneltab[index+0]]<<24 | t[tunneltab[index+1]]<<16 |
  252.          t[tunneltab[index+2]]<<8  | t[tunneltab[index+3]],
  253.     *p++=t[tunneltab[index+4]]<<24 | t[tunneltab[index+5]]<<16 |
  254.          t[tunneltab[index+6]]<<8  | t[tunneltab[index+7]],
  255.     *p++=t[tunneltab[index+8]]<<24 | t[tunneltab[index+9]]<<16 |
  256.          t[tunneltab[index+10]]<<8 | t[tunneltab[index+11]],
  257.     *p++=t[tunneltab[index+12]]<<24| t[tunneltab[index+13]]<<16 |
  258.          t[tunneltab[index+14]]<<8 | t[tunneltab[index+15]],
  259.     index+=16;
  260.  
  261.  
  262. void changepalette(struct awdisplay *display,
  263.   struct awchunky *chunky,ULONG *palette,ULONG palentries) {
  264.  
  265.   ULONG x;
  266.   ULONG *c;
  267.  
  268.   /* clear chunky and force it visible. this is to
  269.      avoid nasty gfx glitch in screen mode. */
  270.  
  271.   x=(chunky->width_align>>4)*chunky->height;
  272.   c=(ULONG *)chunky->framebuffer;
  273.   while (x--) *c++=0,*c++=0,*c++=0,*c++=0;
  274.   awrenderchunky_show(display,chunky);
  275.     
  276.   awsetpalette(display,palette,palentries);
  277. }
  278.  
  279. ULONG myidcmp(struct IntuiMessage *msg) {
  280.  
  281.   switch (msg->Class) {
  282.     case IDCMP_RAWKEY:
  283.       printf("myidcmp: rawkey 0x%02x\n",msg->Code);
  284.       break;
  285.     case IDCMP_VANILLAKEY:
  286.       printf("myidcmp: vanillakey %c (%d)\n",
  287.         ((msg->Code>31)&&(msg->Code<127))?msg->Code:'.',msg->Code);
  288.       break;
  289.   }
  290.   return AWIDHA_NOP;
  291. }
  292.  
  293. #if defined(__SASC)
  294. const char Version[] = "$VER: " AWINDEMOVERSION " " __AMIGADATE__ ;
  295. #else
  296. const char Version[] = "$VER: " AWINDEMOVERSION " (" __DATE__  ")";
  297. #endif
  298.  
  299. int main(void) {
  300.  
  301.   struct awfile *bunnypic,*bunnypal,*glas2pal;
  302.   struct awchunky *tunchunky,*rotchunky,*plasmachunky;
  303.   struct awdisplay *display;
  304.   struct awtimer *timer;
  305.   struct awodargs odargs;
  306.   struct awrdargs *rdargs;
  307.   LONG array[4]={0};
  308.   ULONG rottime,tuntime,plasmatime;
  309.   ULONG ticks,inputticks=0,time,timebase;
  310.   ULONG frames=0,took,fps100,rotpal=0,tunpal=0;
  311.   ULONG alpha=0,quit=0;
  312.   LONG *sintab;
  313.   UBYTE *texture;
  314.   UWORD *tunneltab,position=0;
  315.  
  316.   if ( (display=awcreatedisplay()) ) {
  317.  
  318.     awsetdebuglevel(display,AWD_VERBOSE);
  319.  
  320.     /* clear all & set default values */
  321.     memset(&odargs,0,sizeof(odargs));
  322.     odargs.flags=AWODAF_INITWINDOW | AWODAF_DIRECTDRAW;
  323.     odargs.modeid8=0L;              /* find best modeid */
  324.     odargs.modeid16=0L;             /* find best modeid */
  325.     odargs.pubscreen="Workbench";   /* Workbench pubscreen */
  326.     odargs.title="awin demo";
  327.     odargs.width=DEF_WIDTH;      /* default dimensions same */
  328.     odargs.height=DEF_HEIGHT;    /* as our "largest" effect's */
  329.     odargs.x=0; odargs.y=0;
  330.  
  331.     rdargs=awreadargs(display,&odargs,
  332.       "PLASMATIME/N,ROTTIME/N,TUNNELTIME/N,STARTTIME/N",array);
  333.  
  334.     if (rdargs) {
  335.  
  336.       printf(
  337.         "   ESC Q quit\n"
  338.         "   W     switch to window mode\n"
  339.         "   S     switch to screen mode\n"
  340.         "   TAB   toggle between window and screen mode\n"
  341.         "   P     pause rendering (handy for screenshots;)\n"
  342.         "   SPACE readjust window size/pos so that it has original w&h\n"
  343.         "   M     change screen mode ModeID (also changes window size)\n\n");
  344.  
  345.       /* now we can modify odargs if we like, although
  346.          overriding user given arguments is rude... :-) */
  347.  
  348.  
  349.       printf("initializing...\n");
  350.  
  351.       bunnypic=awloadfile("bunny.raw");
  352.       bunnypal=awloadfile("bunny.pal");
  353.       tunneltab=init_tunnel();
  354.  
  355.       texture=init_texture(awloadfile("glas2.raw"));
  356.       glas2pal=awloadfile("glas2.pal");
  357.  
  358.       sintab=init_sintab();
  359.  
  360.       if ( (!bunnypic) ||
  361.            (!bunnypal) ||
  362.            (!glas2pal) ||
  363.            (!sintab) ||
  364.            (!tunneltab) ||
  365.            (!texture) ||
  366.            (bunnypic->size!=128*128) ||
  367.            (bunnypal->size!=1024) ||
  368.            (glas2pal->size!=1024) ) {
  369.  
  370.         printf("something went wrong\n");
  371.  
  372.         awfreefile(glas2pal);
  373.         awfreefile(bunnypal); awfreefile(bunnypic);
  374.         awfreeargs(rdargs); awdeletedisplay(display);
  375.         return 10;
  376.       }
  377.  
  378.       /* call myidcmp for IDCMP_RAWKEY and IDCMP_VANILLAKEY */
  379.       awsetidcmphook(display,myidcmp);
  380.       awsetidcmpflags(display,IDCMP_RAWKEY|IDCMP_VANILLAKEY);
  381.  
  382.       if ( (timer=awcreatetimer(display)) ) {
  383.  
  384.         if ( (plasmachunky=awallocchunky(display,
  385.           PLASMA_WIDTH,PLASMA_HEIGHT,PLASMA_DEPTH)) ) {
  386.  
  387.           if ( (rotchunky=awallocchunky(display,
  388.             ROTZOOM_WIDTH,ROTZOOM_HEIGHT,ROTZOOM_DEPTH)) ) {
  389.  
  390.             if ( (tunchunky=awallocchunky(display,
  391.               TUNNEL_WIDTH,TUNNEL_HEIGHT,TUNNEL_DEPTH)) ) {
  392.  
  393.               if (awopendisplay(display,&odargs)) {
  394.  
  395.                 if (array[0]) plasmatime=1000 * *((ULONG *)array[0]);
  396.                   else plasmatime=PLASMA_TIME;
  397.  
  398.                 if (array[1]) rottime=1000 * *((ULONG *)array[1]);
  399.                   else rottime=ROTZOOM_TIME;
  400.  
  401.                 if (array[2]) tuntime=1000 * *((ULONG *)array[2]);
  402.                   else tuntime=TUNNEL_TIME;
  403.  
  404.                 if (array[3]) timebase=-1000 * *((ULONG *)array[3]);
  405.                   else timebase=0;
  406.                 
  407.                 awrestarttimer(timer);
  408.  
  409.                 while (!quit) {
  410.  
  411.                   ticks=awreadtimer(timer);
  412.                   time=ticks-timebase;
  413.  
  414.                   /* handle input 5 times per second, this reduces overhead a
  415.                      bit, but makes awin respond user input a bit sluggish */
  416.                   if (ticks>inputticks) {
  417.                     inputticks=ticks+200;  /* 1s/5=200ms */
  418.                     quit=!awhandleinput(display);
  419.                   }
  420.  
  421.                   if (time<plasmatime) {
  422.  
  423.                     plasma(plasmachunky,time);
  424.                     awrenderchunky(display,plasmachunky);
  425.                     frames++;
  426.  
  427.                   } else if (time<rottime+plasmatime) {
  428.  
  429.                     if (!rotpal) {
  430.                       rotpal++;
  431.                       changepalette(display,rotchunky,(ULONG *)bunnypal->data,256);
  432.                       frames++;
  433.                     }
  434.                     rotzoom(rotchunky,time,&alpha,sintab,bunnypic->data);
  435.                     awrenderchunky(display,rotchunky);
  436.                     frames++;
  437.  
  438.                   } else if (time<tuntime+rottime+plasmatime) {
  439.  
  440.                     if (!tunpal) {
  441.                       tunpal++;
  442.                       changepalette(display,tunchunky,(ULONG *)glas2pal->data,256);
  443.                       frames++;
  444.                     }
  445.                     tunnel(tunchunky,time,&position,tunneltab,sintab,texture);
  446.                     awrenderchunky(display,tunchunky);
  447.                     frames++;
  448.  
  449.                   } else {
  450.                     /* restart */
  451.                     rotpal=0; tunpal=0;
  452.                     timebase+=time;
  453.                   }
  454.                 }
  455.  
  456.                 took=awreadtimer(timer);
  457.                 if (took<50) took=50;
  458.  
  459.                 fps100=frames*1000/(took/100.0);
  460.  
  461.                 printf("ran %lu ms (%lu seconds), %lu frames, %lu.%02lu average fps\n",
  462.                   took,(took+500)/1000,frames,fps100/100,fps100%100);
  463.  
  464.                 awclosedisplay(display);
  465.               }
  466.               awfreechunky(tunchunky);
  467.             }
  468.             awfreechunky(rotchunky);
  469.           }
  470.           awfreechunky(plasmachunky);
  471.         }
  472.         awdeletetimer(timer);
  473.       }
  474.       awfreefile(glas2pal);
  475.       awfreefile(bunnypal);
  476.       awfreefile(bunnypic);
  477.       awfreeargs(rdargs);
  478.     }
  479.     awdeletedisplay(display);
  480.   }
  481.   return 0;
  482. }
  483.